package com.server.tools;

import java.net.URLEncoder;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
* @author	李小布
* @email	397554852@qq.com
* @version	创建时间：2020年12月03日 下午14:35:42
*/
public class AESTools {
	public static final char[] iv_chars = {'1', '2','3','4','5','6','7','8','9'
			,'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
			,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
	/**
	 * 默认key
	 */
	private static final String default_key = "WPJXHWXUEBCEXGEO";
	/**
	 * 默认iv
	 */
	private static final String default_iv = "";
	
	/**
	 * AES加密
	 * @param content 明文
	 * @param _key 加密key
	 * @param _iv 偏移量
	 * @return 密文
	 */
    public static String AESEncrypt(String content, String _key, String _iv, boolean is_urlcode){
    	String data = null;
    	try {
    		if(_key == null)_key = default_key;
        	if(_iv == null)_iv = default_iv;
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] raw = _key.getBytes();
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            IvParameterSpec iv = new IvParameterSpec(_iv.getBytes());// 使用CBC模式，需要一个向量iv，可增加加密算法的强度
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(content.getBytes("utf-8"));
            data = new BASE64Encoder().encode(encrypted);// 此处使用BASE64做转码。
            if(is_urlcode)data = URLEncoder.encode(data, "UTF-8");
    	}
    	catch(Exception e) {
    		e.printStackTrace();
    	}
    	return data;
    }
    
    /**
     * AES IV动态加密
     * @param content
     * @param _key
     * @return 密文
     */
    public static String AESEncrypt(String content, String _key, boolean is_urlcode) {
    	String _iv = GetAIVString();
    	return GetAIVString() + _iv + AESEncrypt(content, _key, _iv, is_urlcode);
    }
    
    /**
     * AES解密
     * @param content 密文
     * @param _key 加密key
	 * @param _iv 偏移量
     * @return 明文
     */
    public static String AESDecrypt(String content, String _key, String _iv) {
    	content = content.replaceAll(" ", "+");
    	String data = null;
        try {
        	if(_key == null)_key = default_key;
        	if(_iv == null)_iv = default_iv;

            byte[] raw = _key.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(_iv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(content);
            byte[] original = cipher.doFinal(encrypted1);
            data = new String(original, "utf-8");
        } catch (Exception e) {
        	e.printStackTrace();
        }
        return data;
    }

    /**
     * AES IV动态解密
     * @param content 密文
     * @param _key 加密key
     * @return 明文
     */
    public static String AESDecrypt(String content, String _key) {
    	String _iv = content.substring(7, 23);
    	content = content.substring(32, content.length());
    	return AESDecrypt(content, _key, _iv);
    }
    
    /**
     * AES IV动态解密
     * @param content 密文
     * @param _key 加密key
     * @return 明文
     */
    public static String AESDecrypt(String content) {
    	String _iv = content.substring(7, 23);
    	String pas_1 = content.substring(0, 7);
    	String pas_2 = content.substring(23, content.length());
    	content = pas_1 + pas_2;
    	return AESDecrypt(content, default_key, _iv);
    }
	
    /**
     * 获取16位长字符串
     * @return 16位长字符串
     */
	public static String GetAIVString() {
		Random rand = new Random();
		String str = String.valueOf(iv_chars[rand.nextInt(14) + 33]);
		for(int i = 0 ;i < 15; i++) {
			str += String.valueOf(iv_chars[rand.nextInt(iv_chars.length)]);
		}
		return str;
	}
	
	/**
     * 获取8位长字符串
     * @return 8位长字符串
     */
	public static String GetAEightString() {
		Random rand = new Random();
		String str = String.valueOf(iv_chars[rand.nextInt(14) + 33]);
		for(int i = 0 ;i < 7; i++) {
			str += String.valueOf(iv_chars[rand.nextInt(iv_chars.length)]);
		}
		return str;
	}
}
